library(shades)
Attaching package: ‘shades’
The following object is masked from ‘package:phyloseq’:
distance
The following object is masked from ‘package:ape’:
complement
Read in and Prep-process data
Read in Taxa Tables
taxa_table <- read_table('../../results/metaphlan_bowtie_out/merged_metaphlan_profile.tsv',skip = 1) %>%
select(!clade_taxid)
# Remove .metaphlan_profile from ends of files
colnames(taxa_table) <- sapply(strsplit(names(taxa_table), ".metaphlan_profile"), `[[`, 1)
taxa_table <- taxa_table %>% select(!"20221221-Comunal-Zymo")
genus_table <- taxa_table %>% filter(grepl("g__", clade_name), !grepl("s__", clade_name))
genus_table <- genus_table %>% column_to_rownames(var = c("clade_name"))
species_table <- taxa_table %>% filter(grepl("s__", clade_name))
species_table <- species_table %>% column_to_rownames(var = c("clade_name"))
find samples with 100% unknown and remove them
samples.unknown <- species_table %>%
melt () %>%
group_by(variable) %>%
summarise(sum=sum(value)) %>%
filter(sum == 0) %>%
pluck(1) %>%
as.vector()
# Remove samples with no known taxa
species_table <- species_table[, -which(names(species_table) %in% samples.unknown)]
read in map table
mgx <- read_csv("../../results/minimal_SCRIPT_01_Metagenomics.csv", name_repair = "universal") %>%
select(Sample, DNA.tube.ID, Batch_sample) %>%
rename(tube = "DNA.tube.ID", file_name = "Batch_sample") %>%
filter(file_name %in% colnames(species_table)) %>%
mutate(Sample = stringr::str_replace_all(Sample, "-", ""))
amp <- clusters %>%
separate(name, into=c("Sample", "tube"), sep = "-TUBE") %>%
mutate(Sample = stringr::str_replace_all(Sample, "PT", "")) %>%
mutate(cluster_num = as.factor(cluster_num)) %>%
filter(tube %in% mgx$tube)
map_table <- mgx %>%
left_join(amp) %>%
column_to_rownames("file_name") %>%
filter(!rownames(.) %in% samples.unknown) %>%
filter(!is.na(cluster_num))
remove neg controls; set sample.type factor
species_table <- species_table[,rownames(map_table)] # reorder to match metadata
genus_table <- genus_table[,rownames(map_table)]
all(row.names(map_table) %in% colnames(species_table))
Testing as phyloseq + Playground
MPA
library(tidyverse); packageVersion("tidyverse") #version:1.3.0
library(phyloseq); packageVersion("phyloseq") #version:1.32.0
#Building MetaPhlAn species abundance ps object
s_abund <- species_table %>%
rownames_to_column(var="taxonomy")
s_tax_tab <- s_abund %>%
dplyr::select(taxonomy) %>%
tidyr::separate(taxonomy, into = c("Kingdom", "Phylum", "Class", "Order", "Family", "Genus", "Species"), sep = "\\|") %>%
dplyr::mutate(spec_row = Species) %>%
tibble::column_to_rownames(var = "spec_row") %>%
filter(Kingdom == "k__Bacteria")
s_otu_tab <- s_abund %>%
tidyr::separate(taxonomy, into = c("Kingdom", "Phylum", "Class", "Order", "Family", "Genus", "Species"), sep = "\\|") %>%
filter(Kingdom != "k__Bacteria") %>%
dplyr::select(-Kingdom, -Phylum, -Class, -Order, -Family, -Genus) %>%
tibble::column_to_rownames(var == "Species")
names(s_otu_tab) <- gsub(names(s_otu_tab), pattern = ".metaphlan_profile", replacement = "")
head(colSums(s_otu_tab))
s_otu_tab <- s_otu_tab / 100 #convert to proportion with unit sum of 1
head(colSums(s_otu_tab))
s_meta <- data.frame(seq_id = names(s_otu_tab))
s_meta <- s_meta %>%
left_join(
rownames_to_column(map_table),
by=c("seq_id" = "rowname")) %>%
dplyr::mutate(sampleNames_row = seq_id) %>%
tibble::column_to_rownames(var = "sampleNames_row") %>%
mutate(sample.id = paste0("PT", Sample, "-TUBE", tube))
(ps_mpa3 <- phyloseq(sample_data(s_meta),
otu_table(s_otu_tab, taxa_are_rows = TRUE),
tax_table(as.matrix(s_tax_tab))))
ps_mpa3 <- prune_samples(sample_sums(ps_mpa3) > 0, ps_mpa3)
ps_mpa3 <- microbiome::transform(ps_mpa3,
transform = "compositional",
target="Genus")
ps_mpa3.gen <- tax_glom(ps_mpa3, taxrank = "Genus",NArm=FALSE)
library(vegan)
decostand(s_otu_tab, method="normalize", MARGIN=1)
View(otu_table(ps_mpa3))
Bray Curtis Distance
dist.amp.bray <-as.matrix(distance(subset_samples(ps.gen.comp, sample.id %in% s_meta$sample.id), method="bray", type="samples"))
dist.mpa.bray <-as.matrix(distance(ps_mpa3.gen, method="bray", type="samples"))
dist.krak.bray <-as.matrix(distance(ps_kraken_species.css, method="bray", type="samples"))
PCoA
PCoA
jacc.pcoa <- pcoa(dist.amp.bray)
pcoa.pt <- jacc.pcoa$vectors %>%
as_tibble(rownames = NA) %>%
rownames_to_column()
pcoa.pt <- pcoa.pt %>% select(1:20) %>%
left_join(s_meta, by=c("rowname"="sample.id"))
p.wu <-ggplot(pcoa.pt, aes(Axis.1, Axis.2))+
geom_point(aes(color=factor(cluster_num)),size=1, alpha=0) +
theme_bw(10) +
theme(legend.position = "left") +
labs(x="PCoA1",y="PCoA2") +
#scale_color_brewer(palette="Set1")+
scale_color_npg() +
theme(axis.title = element_text(size = 8)) +
geom_point(aes(fill=factor(cluster_num)),size=3, alpha=1, shape=21) +
scale_fill_npg() +
#scale_fill_brewer(palette="Set1") +
nature_theme("PCoA1", "PCoA1") +
theme(legend.position = "bottom") + coord_fixed(ratio=1) + ggtitle("Amplicon Bray Curtis")
p.wu


jacc.pcoa <- pcoa(dist.mpa.bray)
pcoa.pt <- jacc.pcoa$vectors %>%
as_tibble(rownames = NA) %>%
rownames_to_column()
pcoa.pt <- pcoa.pt %>% select(1:20) %>%
left_join(s_meta, by=c("rowname"="seq_id"))
Error in `select()`:
! Can't subset columns past the end.
ℹ Locations 9, 10, 11, …, 19, and 20 don't exist.
ℹ There are only 8 columns.
Backtrace:
1. pcoa.pt %>% select(1:20) %>% ...
4. dplyr:::select.data.frame(., 1:20)


UMAP UniFrac W
# Unifrac Settings
library(ggExtra)
library(umap)
# Set UMAP config (see knight 2021 umap paper)
umap.config<-umap::umap.defaults
umap.config$n_neighbors <- length(sample_names(ps_kraken_species))-1
umap.config$min_dist <- .9
umap.config$spread <- 1
umap.config$random_state <- 1234567
umap.config$transform_state <- 123
do_umap_mgx2amp <- function(dist.matrix, umap_config,join_var){
# Run UMAP
fun.umap <- umap::umap(dist.matrix, config = umap_config,input="dist")
# Get Coordinates for ggplot2
umap.pt <- fun.umap$layout %>%
as_tibble(rownames = NA) %>%
rownames_to_column()
# Join with extra metadata, clusters, etc.
umap.pt <- umap.pt %>%
left_join(s_meta, by=c("rowname"=join_var))
# Plot UMAP
p.umap <-ggplot(umap.pt, aes(x=V1, y=V2))+
geom_point(aes(color=factor(cluster_num)),size=1, alpha=0) +
theme_bw(10) +
theme(legend.position = "left") +
labs(x="UMAP1",y="UMAP2") +
#scale_color_brewer(palette="Set1")+
scale_color_npg() +
theme(axis.title = element_text(size = 8)) +
geom_point(aes(fill=factor(cluster_num)),size=2, alpha=1, shape=21) +
scale_fill_npg() +
#scale_fill_brewer(palette="Set1") +
nature_theme("UMAP1", "UMAP2") +
theme(legend.position = "bottom") + theme(aspect.ratio=1)
p.ellipse <- p.umap + stat_ellipse(aes(color = factor(cluster_num))) #+ theme(legend.position = "none")
# Optional Plot with Marginal Distributions
p.marginal<-ggMarginal(p.umap, type="density", groupFill = T, groupColour = T)
return(list(p.umap, p.ellipse, p.marginal, umap.pt))
}
p.umaps.amp <- do_umap_mgx2amp(dist.amp.bray, umap.config, "sample.id")
p.umaps.amp[[3]]
p.umaps.krak <- do_umap_mgx2amp(dist.krak.bray, umap.config, "seq_id")
p.umaps.krak[[4]] %>%
left_join(meta) %>%
ggplot(., aes(x=V1, y=V2))+
geom_point(aes(color=factor(cluster_num)),size=1, alpha=0) +
geom_point(aes(fill=factor(cluster_num)),size=2, alpha=1, shape=21) +
stat_ellipse(aes(color = factor(cluster_num))) +
scale_color_npg() +
scale_fill_npg() +
labs(x="UMAP1",y="UMAP2") +
nature_theme("UMAP1", "UMAP2") +
theme(aspect.ratio=1,legend.position = "bottom", axis.title = element_text(size = 8))
p.umaps.krak[[3]]
p.umaps.krak[[4]] %>%
left_join(meta) %>%
ggplot(., aes(x=V1, y=V2))+
#geom_point(color="grey", size=1, alpha=.01) +
geom_point(aes(fill=antibiotics_48h),size=2, alpha=1, shape=21) +
scale_fill_npg() +
labs(x="UMAP1",y="UMAP2") +
nature_theme("UMAP1", "UMAP2") +
theme(aspect.ratio=1,legend.position = "bottom", axis.title = element_text(size = 8))
library(ade4)
tmp.mant <- mantel.rtest(as.dist(dist.amp.bray), as.dist(dist.krak.bray), nrepet = 999)
tmp.mant$^2
Visualize Specific Features
psmelt(ps_kraken_species) %>%
arrange(Sample) %>%
mutate(OTU = stringr::str_replace(string = OTU, pattern = "-", replacement=".")) %>%
#filter(Sample %in% c("DNA_B02_27")) %>%
filter(str_detect(OTU, "k__Viruses")) %>%
group_by(cluster_num) %>%
summarize(min = min(Abundance),
q1 = quantile(value, 0.25),
median = median(value),
mean = mean(value),
q3 = quantile(value, 0.75),
max = max(value))
Warning in psmelt(ps_kraken_species) :
The sample variables:
Sample
have been renamed to:
sample_Sample
to avoid conflicts with special phyloseq plot attribute names.
Error in `summarize()`:
ℹ In argument: `q1 = quantile(value, 0.25)`.
ℹ In group 1: `cluster_num = 1`.
Caused by error in `quantile()`:
! object 'value' not found
Backtrace:
1. ... %>% ...
11. stats::quantile(value, 0.25)
Maaslin Genera
meta_4mas <- sample_data(ps_kraken_species) %>%
as.data.frame() %>%
as_tibble(rownames = NA) %>%
select(sample.id, seq_id, cluster_num) %>%
left_join(select(meta, sample.id, pt_category, success,patient.id.num)) %>%
column_to_rownames("seq_id") #%>% mutate(cluster_num = if_else(cluster_num == "4", "0", cluster_num))
Joining with `by = join_by(sample.id)`
krakenMGX = Maaslin2(input_data = kraken_4mas,
input_metadata = meta_4mas,
min_abundance = .001,
min_prevalence = .1,
#normalization = "TSS",
transform = "AST",
output = "../../results/notebook_out/maaslin2_out",
fixed_effects = c("cluster_num"),
reference = c("cluster_num,4"),
random_effects = c("patient.id.num"),
core = 4,plot_scatter = FALSE
) # Subject
[1] "Warning: Deleting existing log file: ../../results/notebook_out/maaslin2_out/maaslin2.log"
2023-04-26 15:00:14 INFO::Writing function arguments to log file
2023-04-26 15:00:14 INFO::Verifying options selected are valid
2023-04-26 15:00:14 INFO::Determining format of input files
2023-04-26 15:00:14 INFO::Input format is data samples as rows and metadata samples as rows
2023-04-26 15:00:14 INFO::Formula for random effects: expr ~ (1 | patient.id.num)
2023-04-26 15:00:14 INFO::Formula for fixed effects: expr ~ cluster_num
2023-04-26 15:00:14 INFO::Filter data based on min abundance and min prevalence
2023-04-26 15:00:14 INFO::Total samples in data: 202
2023-04-26 15:00:14 INFO::Min samples required with min abundance for a feature not to be filtered: 20.200000
2023-04-26 15:00:14 INFO::Total filtered features: 1402
2023-04-26 15:00:14 INFO::Filtered feature names from abundance and prevalence filtering:
2023-04-26 15:00:14 INFO::Total filtered features with variance filtering: 0
2023-04-26 15:00:14 INFO::Filtered feature names from variance filtering:
2023-04-26 15:00:14 INFO::Running selected normalization method: TSS
2023-04-26 15:00:14 INFO::Applying z-score to standardize continuous metadata
2023-04-26 15:00:14 INFO::Running selected transform method: AST
2023-04-26 15:00:14 INFO::Running selected analysis method: LM
2023-04-26 15:00:14 INFO::Creating cluster of 4 R processes
| | 0 % ~calculating
|+++ | 6 % ~43s
|++++++ | 11% ~21s
|+++++++++ | 17% ~14s
|++++++++++++ | 22% ~11s
|++++++++++++++ | 28% ~08s
|+++++++++++++++++ | 33% ~07s
|++++++++++++++++++++ | 39% ~06s
|+++++++++++++++++++++++ | 44% ~05s
|+++++++++++++++++++++++++ | 50% ~04s
|++++++++++++++++++++++++++++ | 56% ~03s
|+++++++++++++++++++++++++++++++ | 61% ~03s
|++++++++++++++++++++++++++++++++++ | 67% ~02s
|+++++++++++++++++++++++++++++++++++++ | 72% ~02s
|+++++++++++++++++++++++++++++++++++++++ | 78% ~01s
|++++++++++++++++++++++++++++++++++++++++++ | 83% ~01s
|+++++++++++++++++++++++++++++++++++++++++++++ | 89% ~01s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 94% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=06s
2023-04-26 15:00:21 INFO::Counting total values for each feature
2023-04-26 15:00:21 WARNING::Deleting existing residuals file: ../../results/notebook_out/maaslin2_out/residuals.rds
2023-04-26 15:00:21 INFO::Writing residuals to file ../../results/notebook_out/maaslin2_out/residuals.rds
2023-04-26 15:00:21 WARNING::Deleting existing fitted file: ../../results/notebook_out/maaslin2_out/fitted.rds
2023-04-26 15:00:21 INFO::Writing fitted values to file ../../results/notebook_out/maaslin2_out/fitted.rds
2023-04-26 15:00:21 WARNING::Deleting existing ranef file: ../../results/notebook_out/maaslin2_out/ranef.rds
2023-04-26 15:00:21 INFO::Writing extracted random effects to file ../../results/notebook_out/maaslin2_out/ranef.rds
2023-04-26 15:00:21 INFO::Writing all results to file (ordered by increasing q-values): ../../results/notebook_out/maaslin2_out/all_results.tsv
2023-04-26 15:00:21 INFO::Writing the significant results (those which are less than or equal to the threshold of 0.250000 ) to file (ordered by increasing q-values): ../../results/notebook_out/maaslin2_out/significant_results.tsv
2023-04-26 15:00:21 INFO::Writing heatmap of significant results to file: ../../results/notebook_out/maaslin2_out/heatmap.pdf
Warning in xtfrm.data.frame(x) : cannot xtfrm data frames


maaslin_norm.gen <- krakenMGX$results %>% as.data.frame()
maaslin_norm.gen$OTU <- rownames(maaslin_norm.gen)
maaslin_norm.gen <- maaslin_norm.gen %>%
#separate(feature, into=c("ASV", "feature"), sep = "[.]") %>%
filter(qval < 0.00001) %>%
filter(N.not.zero > 10) %>%
arrange(qval) %>%
select(feature) %>%
unique
diff.genera <- maaslin_norm.gen$feature
sort(diff.genera)
[1] "Corynebacterium_genitalium" "Corynebacterium_kefirresidentii"
[3] "Corynebacterium_singulare" "Corynebacterium_striatum"
[5] "Cutibacterium_acnes" "Gemella_haemolysans"
[7] "Lacticaseibacillus_rhamnosus" "Lancefieldella_parvula"
[9] "Mogibacterium_diversum" "Moraxella_osloensis"
[11] "Olsenella_uli" "Parvimonas_micra"
[13] "Prevotella_jejuni" "Rothia_mucilaginosa"
[15] "Schaalia_odontolytica" "Staphylococcus_capitis"
[17] "Staphylococcus_epidermidis" "Staphylococcus_hominis"
[19] "Streptococcus_anginosus" "Streptococcus_parasanguinis"
[21] "Streptococcus_salivarius" "Streptococcus_sp._HSISM1"
[23] "Streptococcus_sp._LPB0220" "Streptococcus_sp._oral_taxon_061"
[25] "Streptococcus_sp._oral_taxon_431"
otu.ast.krak.phy <- psmelt(ps.ast.krak.phy) %>%
mutate(Abundance = sign(Abundance)*asin(sqrt(abs(Abundance)))) %>% # if want AST transform
arrange(Sample) %>%
select(Sample, OTU, Abundance) %>%
pivot_wider(id_cols = OTU, names_from = Sample, values_from = Abundance) %>%
column_to_rownames(var="OTU") %>%
as.matrix()
Warning in psmelt(ps.ast.krak.phy) :
The sample variables:
Sample
have been renamed to:
sample_Sample
to avoid conflicts with special phyloseq plot attribute names.
psmelt(ps_kraken_phyla) %>%
select(Sample,Abundance, Species,cluster_num) %>%
# mutate(k__Viruses = log10(k__Viruses),
# k__Bacteria = log10(k__Bacteria),
# k__Eukaryota = log10(k__Eukaryota)) %>%
ggplot(., aes(x=cluster_num, y=Abundance, fill=Species, group=cluster_num)) +
geom_boxplot(aes(fill=Species), outlier.alpha = 0) +
geom_point(aes(fill=Species),
alpha = 0.75,
size = 1,
shape = 21,
color = 'black',
position = position_jitterdodge(jitter.width = .5)) +
scale_fill_simpsons() +
nature_theme("Read", "Fol") +
labs(x="Pneumotype Cluster" ,
y="Domain Abundance",
title="Domain Level Shifts in Metagenomic Data (AST Normalized)") +
theme(aspect.ratio = 1) + facet_grid(~Species) +
stat_compare_means(label.y.npc = .95,size=2,label.x.npc = "center")
Warning in psmelt(ps_kraken_phyla) :
The sample variables:
Sample
have been renamed to:
sample_Sample
to avoid conflicts with special phyloseq plot attribute names.
LS0tCnRpdGxlOiAiMDJBX01ldGFQaGxhblRheG9ub21pYzJBTVAiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KHZlZ2FuKQpsaWJyYXJ5KG1ldGFnZW5vbWVTZXEpCmxpYnJhcnkoZ2dyaWRnZXMpCmxpYnJhcnkoc2hhZGVzKQoKYGBgCgojIFJlYWQgaW4gYW5kIFByZXAtcHJvY2VzcyBkYXRhCiMjIFJlYWQgaW4gVGF4YSBUYWJsZXMKYGBge3J9Cgp0YXhhX3RhYmxlIDwtIHJlYWRfdGFibGUoJy4uLy4uL3Jlc3VsdHMvbWV0YXBobGFuX2Jvd3RpZV9vdXQvbWVyZ2VkX21ldGFwaGxhbl9wcm9maWxlLnRzdicsc2tpcCA9IDEpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdCghY2xhZGVfdGF4aWQpCgoKIyBSZW1vdmUgLm1ldGFwaGxhbl9wcm9maWxlIGZyb20gZW5kcyBvZiBmaWxlcyAKY29sbmFtZXModGF4YV90YWJsZSkgPC0gc2FwcGx5KHN0cnNwbGl0KG5hbWVzKHRheGFfdGFibGUpLCAiLm1ldGFwaGxhbl9wcm9maWxlIiksIGBbW2AsIDEpCnRheGFfdGFibGUgPC0gdGF4YV90YWJsZSAlPiUgc2VsZWN0KCEiMjAyMjEyMjEtQ29tdW5hbC1aeW1vIikKZ2VudXNfdGFibGUgPC0gdGF4YV90YWJsZSAlPiUgZmlsdGVyKGdyZXBsKCJnX18iLCBjbGFkZV9uYW1lKSwgIWdyZXBsKCJzX18iLCBjbGFkZV9uYW1lKSkKZ2VudXNfdGFibGUgPC0gZ2VudXNfdGFibGUgJT4lIGNvbHVtbl90b19yb3duYW1lcyh2YXIgPSBjKCJjbGFkZV9uYW1lIikpCgpzcGVjaWVzX3RhYmxlIDwtIHRheGFfdGFibGUgJT4lIGZpbHRlcihncmVwbCgic19fIiwgY2xhZGVfbmFtZSkpCnNwZWNpZXNfdGFibGUgPC0gc3BlY2llc190YWJsZSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKHZhciA9IGMoImNsYWRlX25hbWUiKSkKYGBgCgojIGZpbmQgc2FtcGxlcyB3aXRoIDEwMCUgdW5rbm93biBhbmQgcmVtb3ZlIHRoZW0KYGBge3J9CnNhbXBsZXMudW5rbm93biA8LSBzcGVjaWVzX3RhYmxlICU+JSAKICBtZWx0ICgpICU+JSAKICBncm91cF9ieSh2YXJpYWJsZSkgJT4lIAogIHN1bW1hcmlzZShzdW09c3VtKHZhbHVlKSkgJT4lIAogIGZpbHRlcihzdW0gPT0gMCkgJT4lIAogIHBsdWNrKDEpICU+JSAKICBhcy52ZWN0b3IoKQoKIyBSZW1vdmUgc2FtcGxlcyB3aXRoIG5vIGtub3duIHRheGEKc3BlY2llc190YWJsZSA8LSBzcGVjaWVzX3RhYmxlWywgLXdoaWNoKG5hbWVzKHNwZWNpZXNfdGFibGUpICVpbiUgc2FtcGxlcy51bmtub3duKV0gCmBgYAoKCgojIHJlYWQgaW4gbWFwIHRhYmxlCmBgYHtyfQptZ3ggPC0gcmVhZF9jc3YoIi4uLy4uL3Jlc3VsdHMvbWluaW1hbF9TQ1JJUFRfMDFfTWV0YWdlbm9taWNzLmNzdiIsIG5hbWVfcmVwYWlyID0gInVuaXZlcnNhbCIpICU+JQogIHNlbGVjdChTYW1wbGUsIEROQS50dWJlLklELCBCYXRjaF9zYW1wbGUpICU+JQogIHJlbmFtZSh0dWJlID0gIkROQS50dWJlLklEIiwgZmlsZV9uYW1lID0gIkJhdGNoX3NhbXBsZSIpICU+JQogIGZpbHRlcihmaWxlX25hbWUgJWluJSBjb2xuYW1lcyhzcGVjaWVzX3RhYmxlKSkgJT4lCiAgbXV0YXRlKFNhbXBsZSA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChTYW1wbGUsICItIiwgIiIpKQphbXAgPC0gY2x1c3RlcnMgJT4lCiAgc2VwYXJhdGUobmFtZSwgaW50bz1jKCJTYW1wbGUiLCAidHViZSIpLCBzZXAgPSAiLVRVQkUiKSAlPiUKICBtdXRhdGUoU2FtcGxlID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKFNhbXBsZSwgIlBUIiwgIiIpKSAlPiUKICBtdXRhdGUoY2x1c3Rlcl9udW0gPSBhcy5mYWN0b3IoY2x1c3Rlcl9udW0pKSAlPiUKICBmaWx0ZXIodHViZSAlaW4lIG1neCR0dWJlKQptYXBfdGFibGUgPC0gbWd4ICU+JSAKICBsZWZ0X2pvaW4oYW1wKSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXMoImZpbGVfbmFtZSIpICU+JSAKICBmaWx0ZXIoIXJvd25hbWVzKC4pICVpbiUgc2FtcGxlcy51bmtub3duKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGNsdXN0ZXJfbnVtKSkKCmBgYAoKCiMjIHJlbW92ZSBuZWcgY29udHJvbHM7IHNldCBzYW1wbGUudHlwZSBmYWN0b3IKYGBge3J9CnNwZWNpZXNfdGFibGUgPC0gc3BlY2llc190YWJsZVsscm93bmFtZXMobWFwX3RhYmxlKV0gIyByZW9yZGVyIHRvIG1hdGNoIG1ldGFkYXRhCgpnZW51c190YWJsZSA8LSBnZW51c190YWJsZVsscm93bmFtZXMobWFwX3RhYmxlKV0KCmFsbChyb3cubmFtZXMobWFwX3RhYmxlKSAlaW4lIGNvbG5hbWVzKHNwZWNpZXNfdGFibGUpKQpgYGAKCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgVGVzdGluZyBhcyBwaHlsb3NlcSArIFBsYXlncm91bmQKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIE1QQQpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpOyBwYWNrYWdlVmVyc2lvbigidGlkeXZlcnNlIikgICAgICN2ZXJzaW9uOjEuMy4wIApsaWJyYXJ5KHBoeWxvc2VxKTsgcGFja2FnZVZlcnNpb24oInBoeWxvc2VxIikgICAgICAgI3ZlcnNpb246MS4zMi4wCgoKI0J1aWxkaW5nIE1ldGFQaGxBbiBzcGVjaWVzIGFidW5kYW5jZSBwcyBvYmplY3QKc19hYnVuZCA8LSBzcGVjaWVzX3RhYmxlICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXI9InRheG9ub215IikKCnNfdGF4X3RhYiA8LSBzX2FidW5kICU+JQogIGRwbHlyOjpzZWxlY3QodGF4b25vbXkpICU+JQogIHRpZHlyOjpzZXBhcmF0ZSh0YXhvbm9teSwgaW50byA9IGMoIktpbmdkb20iLCAiUGh5bHVtIiwgIkNsYXNzIiwgIk9yZGVyIiwgIkZhbWlseSIsICJHZW51cyIsICJTcGVjaWVzIiksIHNlcCA9ICJcXHwiKSAlPiUKICBkcGx5cjo6bXV0YXRlKHNwZWNfcm93ID0gU3BlY2llcykgJT4lCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXModmFyID0gInNwZWNfcm93IikgJT4lCiAgZmlsdGVyKEtpbmdkb20gPT0gImtfX0JhY3RlcmlhIikKCnNfb3R1X3RhYiA8LSBzX2FidW5kICU+JQogIHRpZHlyOjpzZXBhcmF0ZSh0YXhvbm9teSwgaW50byA9IGMoIktpbmdkb20iLCAiUGh5bHVtIiwgIkNsYXNzIiwgIk9yZGVyIiwgIkZhbWlseSIsICJHZW51cyIsICJTcGVjaWVzIiksIHNlcCA9ICJcXHwiKSAlPiUKICBmaWx0ZXIoS2luZ2RvbSAhPSAia19fQmFjdGVyaWEiKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1LaW5nZG9tLCAtUGh5bHVtLCAtQ2xhc3MsIC1PcmRlciwgLUZhbWlseSwgLUdlbnVzKSAlPiUKICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcyh2YXIgPT0gIlNwZWNpZXMiKQoKbmFtZXMoc19vdHVfdGFiKSA8LSBnc3ViKG5hbWVzKHNfb3R1X3RhYiksIHBhdHRlcm4gPSAiLm1ldGFwaGxhbl9wcm9maWxlIiwgcmVwbGFjZW1lbnQgPSAiIikgCgpoZWFkKGNvbFN1bXMoc19vdHVfdGFiKSkKc19vdHVfdGFiIDwtIHNfb3R1X3RhYiAvIDEwMCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNjb252ZXJ0IHRvIHByb3BvcnRpb24gd2l0aCB1bml0IHN1bSBvZiAxCmhlYWQoY29sU3VtcyhzX290dV90YWIpKQoKc19tZXRhIDwtIGRhdGEuZnJhbWUoc2VxX2lkID0gbmFtZXMoc19vdHVfdGFiKSkKc19tZXRhIDwtIHNfbWV0YSAlPiUKICBsZWZ0X2pvaW4oCiAgIHJvd25hbWVzX3RvX2NvbHVtbihtYXBfdGFibGUpLCAKICAgIGJ5PWMoInNlcV9pZCIgPSAicm93bmFtZSIpKSAlPiUgIAogIGRwbHlyOjptdXRhdGUoc2FtcGxlTmFtZXNfcm93ID0gc2VxX2lkKSAlPiUKICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAic2FtcGxlTmFtZXNfcm93IikgJT4lCiAgbXV0YXRlKHNhbXBsZS5pZCA9IHBhc3RlMCgiUFQiLCBTYW1wbGUsICItVFVCRSIsIHR1YmUpKQoKCihwc19tcGEzIDwtIHBoeWxvc2VxKHNhbXBsZV9kYXRhKHNfbWV0YSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3R1X3RhYmxlKHNfb3R1X3RhYiwgdGF4YV9hcmVfcm93cyA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheF90YWJsZShhcy5tYXRyaXgoc190YXhfdGFiKSkpKQpwc19tcGEzIDwtIHBydW5lX3NhbXBsZXMoc2FtcGxlX3N1bXMocHNfbXBhMykgPiAwLCBwc19tcGEzKQpwc19tcGEzIDwtIG1pY3JvYmlvbWU6OnRyYW5zZm9ybShwc19tcGEzLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJjb21wb3NpdGlvbmFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PSJHZW51cyIpCnBzX21wYTMuZ2VuIDwtIHRheF9nbG9tKHBzX21wYTMsIHRheHJhbmsgPSAiR2VudXMiLE5Bcm09RkFMU0UpCgpsaWJyYXJ5KHZlZ2FuKQpkZWNvc3RhbmQoc19vdHVfdGFiLCBtZXRob2Q9Im5vcm1hbGl6ZSIsIE1BUkdJTj0xKQpWaWV3KG90dV90YWJsZShwc19tcGEzKSkKCmBgYAoKIyMgS1JBS0VOCmBgYHtyfQojIEZvciBTcGVjaWVzLUxldmVsIEFuYWx5c2lzCnNfYWJ1bmQgPC0gcmVhZF90c3YoIi4uLy4uL3Jlc3VsdHMva3Jha2VuL21lcmdlZF9rcmFrZW5fbXBhX3Byb2ZpbGUudHN2IikgJT4lCiAgcmVuYW1lKGNsYWRlX25hbWUgPSAiI0NsYXNzaWZpY2F0aW9uIikgJT4lCiAgZmlsdGVyKGdyZXBsKCJzX18iLCBjbGFkZV9uYW1lKSkKCnNfdGF4X3RhYiA8LSBzX2FidW5kICU+JQogIGRwbHlyOjpyZW5hbWUoInRheG9ub215IiA9ICJjbGFkZV9uYW1lIikgJT4lCiAgI2ZpbHRlcihzdHJpbmdyOjpzdHJfZGV0ZWN0KHRheG9ub215LHBhdHRlcm4gPSAia19fQmFjdGVyaWEiKSkgJT4lICMgKy8tIE5vbi1CYWNzPwogIGRwbHlyOjpzZWxlY3QodGF4b25vbXkpICU+JQogIGRwbHlyOjptdXRhdGUoU3BlY2llcyA9IHN1YignLipcXHwnLCAnJywgdGF4b25vbXkpLAogICAgICAgICAgICAgICAgU3BlY2llcyA9IGdzdWIoInNfXyIsICIiLCBTcGVjaWVzKSwKICAgICAgICAgICAgICAgIHNwZWNfcm93ID0gdGF4b25vbXkpICU+JSNTcGVjaWVzKSAlPiUKICBkcGx5cjo6c2VsZWN0KC10YXhvbm9teSkgJT4lCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXModmFyID0gInNwZWNfcm93IikKCgpzX290dV90YWIgPC0gc19hYnVuZCAlPiUKICBkcGx5cjo6cmVuYW1lKCJ0YXhvbm9teSIgPSAiY2xhZGVfbmFtZSIpICU+JQogICNmaWx0ZXIoc3RyaW5ncjo6c3RyX2RldGVjdCh0YXhvbm9teSxwYXR0ZXJuID0gImtfX0JhY3RlcmlhIikpICU+JSAjICsvLSBOb24tQmFjcz8KICAjIGRwbHlyOjptdXRhdGUodGF4b25vbXkgPSBzdWIoJy4qXFx8JywgJycsIHRheG9ub215KSwKICAjICAgICAgICAgICAgICAgdGF4b25vbXkgPSBnc3ViKCJzX18iLCAiIiwgdGF4b25vbXkpKSAlPiUKICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAidGF4b25vbXkiKQoKCiMgIyBGb3IgR2VuZXJhLUxldmVsIEFuYWx5c2lzCiMgc19hYnVuZCA8LSByZWFkX3RzdigiLi4vLi4vcmVzdWx0cy9rcmFrZW4vbWVyZ2VkX2tyYWtlbl9tcGFfcHJvZmlsZS50c3YiKSAlPiUKIyAgIHJlbmFtZShjbGFkZV9uYW1lID0gIiNDbGFzc2lmaWNhdGlvbiIpICU+JSAKIyAgIGZpbHRlcihncmVwbCgiZ19fIiwgY2xhZGVfbmFtZSkpICMlPiUgICBmaWx0ZXIoIWdyZXBsKCJzX18iLCBjbGFkZV9uYW1lKSkgJT4lZmlsdGVyKHN0cl9kZXRlY3QoY2xhZGVfbmFtZSwgImtfX0JhY3RlcmlhIikpCiMgCiMgCiMgc190YXhfdGFiIDwtIHNfYWJ1bmQgJT4lCiMgICBkcGx5cjo6cmVuYW1lKCJ0YXhvbm9teSIgPSAiY2xhZGVfbmFtZSIpICU+JQojICAgZHBseXI6OnNlbGVjdCh0YXhvbm9teSkgJT4lCiMgICAjZmlsdGVyKHN0cmluZ3I6OnN0cl9kZXRlY3QodGF4b25vbXkscGF0dGVybiA9ICJrX19CYWN0ZXJpYSIpKSAlPiUgIyArLy0gTm9uLUJhY3M/CiMgICBkcGx5cjo6bXV0YXRlKEdlbnVzID0gc3ViKCcuKlxcfCcsICcnLCB0YXhvbm9teSksCiMgICAgICAgICAgICAgICAgIEdlbnVzID0gZ3N1YigiZ19fIiwgIiIsIEdlbnVzKSwKIyAgICAgICAgICAgICAgICAgc3BlY19yb3cgPSBHZW51cykgJT4lCiMgICBkcGx5cjo6c2VsZWN0KC10YXhvbm9teSkgJT4lCiMgICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAic3BlY19yb3ciKQojIAojIHNfb3R1X3RhYiA8LSBzX2FidW5kICU+JQojICAgZHBseXI6OnJlbmFtZSgidGF4b25vbXkiID0gImNsYWRlX25hbWUiKSAlPiUKIyAgICNmaWx0ZXIoc3RyaW5ncjo6c3RyX2RldGVjdCh0YXhvbm9teSxwYXR0ZXJuID0gImtfX0JhY3RlcmlhIikpICU+JSAjICsvLSBOb24tQmFjcz8KIyAgIGRwbHlyOjptdXRhdGUodGF4b25vbXkgPSBzdWIoJy4qXFx8JywgJycsIHRheG9ub215KSwKIyAgICAgICAgICAgICAgICAgdGF4b25vbXkgPSBnc3ViKCJnX18iLCAiIiwgdGF4b25vbXkpKSAlPiUKIyAgIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJ0YXhvbm9teSIpCgpuYW1lcyhzX290dV90YWIpIDwtIGdzdWIobmFtZXMoc19vdHVfdGFiKSwgcGF0dGVybiA9ICJfa3Jha2VuMnJlcG9ydC50eHQiLCByZXBsYWNlbWVudCA9ICIiKSAKCnNfbWV0YSA8LSBkYXRhLmZyYW1lKHNlcV9pZCA9IG5hbWVzKHNfb3R1X3RhYikpCgpzX21ldGEgPC0gc19tZXRhICU+JQogIGxlZnRfam9pbigKICAgcm93bmFtZXNfdG9fY29sdW1uKG1hcF90YWJsZSksIAogICAgYnk9Yygic2VxX2lkIiA9ICJyb3duYW1lIikpICU+JSAgCiAgZHBseXI6Om11dGF0ZShzYW1wbGVOYW1lc19yb3cgPSBzZXFfaWQpICU+JQogIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJzYW1wbGVOYW1lc19yb3ciKSAlPiUKICBkcm9wX25hKHR1YmUpICU+JQogIG11dGF0ZShzYW1wbGUuaWQgPSBwYXN0ZTAoIlBUIiwgU2FtcGxlLCAiLVRVQkUiLCB0dWJlKSkKCnBzX2tyYWtlbl9zcGVjaWVzIDwtIHBoeWxvc2VxKHNhbXBsZV9kYXRhKHNfbWV0YSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3R1X3RhYmxlKHNfb3R1X3RhYiwgdGF4YV9hcmVfcm93cyA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheF90YWJsZShhcy5tYXRyaXgoc190YXhfdGFiKSkpCgojIEluaXRpYWwgZmlsdGVyaW5nCnBzX2tyYWtlbl9zcGVjaWVzIDwtIGZpbHRlcl90YXhhKHBzX2tyYWtlbl9zcGVjaWVzLCBmdW5jdGlvbih4KXtzdW0oeCA+IDMpID4gMH0sIHBydW5lID0gVFJVRSkKcHNfa3Jha2VuX3NwZWNpZXMgPC0gcHJ1bmVfc2FtcGxlcyhzYW1wbGVfc3Vtcyhwc19rcmFrZW5fc3BlY2llcykgPiA1MDAwLCBwc19rcmFrZW5fc3BlY2llcykKCnBzX2tyYWtlbl9zcGVjaWVzLmNzcyA8LSBwc19rcmFrZW5fc3BlY2llcwpvdHVfdGFibGUocHNfa3Jha2VuX3NwZWNpZXMuY3NzKSA8LSBvdHVfdGFibGUoTVJjb3VudHMocHNfa3Jha2VuX3NwZWNpZXMgJT4lIHBoeWxvc2VxX3RvX21ldGFnZW5vbWVTZXEoKSwgbm9ybSA9IFRSVUUsIGxvZyA9IEZBTFNFKSx0YXhhX2FyZV9yb3dzPVRSVUUpCgoKIyBSZWxhdGl2ZSBBYnVuZGFuY2UgVHJhbnNmb3JtCnBzX2tyYWtlbl9zcGVjaWVzIDwtIG1pY3JvYmlvbWU6OnRyYW5zZm9ybShwc19rcmFrZW5fc3BlY2llcywgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAiY29tcG9zaXRpb25hbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldD0iU3BlY2llcyIpICMgIlNwZWNpZXMiIE9SICJHZW51cyIKCnBzX2tyYWtlbl9zcGVjaWVzCgpwcy5hc3Qua3JhayA8LSBwc19rcmFrZW5fc3BlY2llcwpvdHUuYXN0LmtyYWsgPC0gcHNtZWx0KHBzLmFzdC5rcmFrKSAlPiUgCiAgbXV0YXRlKEFidW5kYW5jZSA9IHNpZ24oQWJ1bmRhbmNlKSphc2luKHNxcnQoYWJzKEFidW5kYW5jZSkpKSkgJT4lICMgaWYgd2FudCBBU1QgdHJhbnNmb3JtCiAgYXJyYW5nZShTYW1wbGUpICU+JQogIHNlbGVjdChTYW1wbGUsIE9UVSwgQWJ1bmRhbmNlKSAlPiUKICBwaXZvdF93aWRlcihpZF9jb2xzID0gT1RVLCBuYW1lc19mcm9tID0gU2FtcGxlLCB2YWx1ZXNfZnJvbSA9IEFidW5kYW5jZSkgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKHZhcj0iT1RVIikgJT4lIAogIGFzLm1hdHJpeCgpIApvdHVfdGFibGUocHMuYXN0LmtyYWspIDwtIG90dV90YWJsZShvdHUuYXN0LmtyYWssIHRheGFfYXJlX3Jvd3MgPSBUUlVFKQoKIyBzYW1wbGVfc3Vtcyhwc19rcmFrZW5fc3BlY2llcykgJT4lIHNvcnQoKQojIHBsb3RfbGlicmFyeV9zaXplKHBzX2NsZWFuKQoKI1ZpZXcob3R1X3RhYmxlKHBzX2tyYWtlbl9zcGVjaWVzKSkKYGBgCgoKCiMgQnJheSBDdXJ0aXMgRGlzdGFuY2UKYGBge3J9CmRpc3QuYW1wLmJyYXkgPC1hcy5tYXRyaXgoZGlzdGFuY2Uoc3Vic2V0X3NhbXBsZXMocHMuZ2VuLmNvbXAsIHNhbXBsZS5pZCAlaW4lIHNfbWV0YSRzYW1wbGUuaWQpLCBtZXRob2Q9ImJyYXkiLCB0eXBlPSJzYW1wbGVzIikpCmRpc3QubXBhLmJyYXkgPC1hcy5tYXRyaXgoZGlzdGFuY2UocHNfbXBhMy5nZW4sIG1ldGhvZD0iYnJheSIsIHR5cGU9InNhbXBsZXMiKSkKZGlzdC5rcmFrLmJyYXkgPC1hcy5tYXRyaXgoZGlzdGFuY2UocHNfa3Jha2VuX3NwZWNpZXMuY3NzLCBtZXRob2Q9ImJyYXkiLCB0eXBlPSJzYW1wbGVzIikpCgpgYGAKCiMgUENvQQojIyMgUENvQQpgYGB7cn0KamFjYy5wY29hIDwtIHBjb2EoZGlzdC5hbXAuYnJheSkKcGNvYS5wdCA8LSBqYWNjLnBjb2EkdmVjdG9ycyAlPiUKICBhc190aWJibGUocm93bmFtZXMgPSBOQSkgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigpCgpwY29hLnB0IDwtIHBjb2EucHQgJT4lIHNlbGVjdCgxOjIwKSAlPiUKICBsZWZ0X2pvaW4oc19tZXRhLCBieT1jKCJyb3duYW1lIj0ic2FtcGxlLmlkIikpCgpwLnd1IDwtZ2dwbG90KHBjb2EucHQsIGFlcyhBeGlzLjEsIEF4aXMuMikpKyAKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yPWZhY3RvcihjbHVzdGVyX251bSkpLHNpemU9MSwgYWxwaGE9MCkgKyAKICAgIHRoZW1lX2J3KDEwKSArIAogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKSArIAogICAgbGFicyh4PSJQQ29BMSIseT0iUENvQTIiKSArCiAgICAjc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSsgIAogICAgc2NhbGVfY29sb3JfbnBnKCkgKwogICAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICsgCiAgICBnZW9tX3BvaW50KGFlcyhmaWxsPWZhY3RvcihjbHVzdGVyX251bSkpLHNpemU9MywgYWxwaGE9MSwgc2hhcGU9MjEpICArIAogICAgc2NhbGVfZmlsbF9ucGcoKSArCiAgICAjc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgICBuYXR1cmVfdGhlbWUoIlBDb0ExIiwgIlBDb0ExIikgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArIGNvb3JkX2ZpeGVkKHJhdGlvPTEpICsgZ2d0aXRsZSgiQW1wbGljb24gQnJheSBDdXJ0aXMiKQoKcC53dQpgYGAKCmBgYHtyfQpqYWNjLnBjb2EgPC0gcGNvYShkaXN0Lm1wYS5icmF5KQpwY29hLnB0IDwtIGphY2MucGNvYSR2ZWN0b3JzICU+JQogIGFzX3RpYmJsZShyb3duYW1lcyA9IE5BKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCkKCnBjb2EucHQgPC0gcGNvYS5wdCAlPiUgc2VsZWN0KDE6MjApICU+JQogIGxlZnRfam9pbihzX21ldGEsIGJ5PWMoInJvd25hbWUiPSJzZXFfaWQiKSkKCnAud3UgPC1nZ3Bsb3QocGNvYS5wdCwgYWVzKEF4aXMuMSwgQXhpcy4yKSkrIAogICAgZ2VvbV9wb2ludChhZXMoY29sb3I9ZmFjdG9yKGNsdXN0ZXJfbnVtKSksc2l6ZT0xLCBhbHBoYT0wKSArIAogICAgdGhlbWVfYncoMTApICsgCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpICsgCiAgICBsYWJzKHg9IlBDb0ExIix5PSJQQ29BMiIpICsKICAgICNzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpKyAgCiAgICBzY2FsZV9jb2xvcl9ucGcoKSArCiAgICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKyAKICAgIGdlb21fcG9pbnQoYWVzKGZpbGw9ZmFjdG9yKGNsdXN0ZXJfbnVtKSksc2l6ZT0zLCBhbHBoYT0xLCBzaGFwZT0yMSkgICsgCiAgICBzY2FsZV9maWxsX25wZygpICsKICAgICNzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICAgIG5hdHVyZV90aGVtZSgiUENvQTEiLCAiUENvQTEiKSArIAogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsgY29vcmRfZml4ZWQocmF0aW89MSkgKyBnZ3RpdGxlKCJNZXRhcGhsYW4gQnJheSBDdXJ0aXMiKQoKcC53dQpgYGAKCmBgYHtyfQpqYWNjLnBjb2EgPC0gcGNvYShkaXN0LmtyYWsuYnJheSkKcGNvYS5wdCA8LSBqYWNjLnBjb2EkdmVjdG9ycyAlPiUKICBhc190aWJibGUocm93bmFtZXMgPSBOQSkgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigpCgpwY29hLnB0IDwtIHBjb2EucHQgJT4lIHNlbGVjdCgxOjIwKSAlPiUKICBsZWZ0X2pvaW4oc19tZXRhLCBieT1jKCJyb3duYW1lIj0ic2VxX2lkIikpCgpwLnd1IDwtZ2dwbG90KHBjb2EucHQsIGFlcyhBeGlzLjEsIEF4aXMuMikpKyAKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yPWZhY3RvcihjbHVzdGVyX251bSkpLHNpemU9MSwgYWxwaGE9MCkgKyAKICAgIHRoZW1lX2J3KDEwKSArIAogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKSArIAogICAgbGFicyh4PSJQQ29BMSIseT0iUENvQTIiKSArCiAgICAjc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSsgIAogICAgc2NhbGVfY29sb3JfbnBnKCkgKwogICAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICsgCiAgICBnZW9tX3BvaW50KGFlcyhmaWxsPWZhY3RvcihjbHVzdGVyX251bSkpLHNpemU9MywgYWxwaGE9MSwgc2hhcGU9MjEpICArIAogICAgc2NhbGVfZmlsbF9ucGcoKSArCiAgICAjc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgICBuYXR1cmVfdGhlbWUoIlBDb0ExIiwgIlBDb0ExIikgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArIGNvb3JkX2ZpeGVkKHJhdGlvPTEpICsgZ2d0aXRsZSgiS3Jha2VuIEJyYXkgQ3VydGlzIikKCnAud3UKCmdnTWFyZ2luYWwocC53dSwgdHlwZT0iZGVuc2l0eSIsIGdyb3VwRmlsbCA9IFQsIGdyb3VwQ29sb3VyID0gVCkKYGBgCgojIyBVTUFQIFVuaUZyYWMgVwpgYGB7cn0KIyBVbmlmcmFjIFNldHRpbmdzIApsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkodW1hcCkKCiMgU2V0IFVNQVAgY29uZmlnIChzZWUga25pZ2h0IDIwMjEgdW1hcCBwYXBlcikKdW1hcC5jb25maWc8LXVtYXA6OnVtYXAuZGVmYXVsdHMKdW1hcC5jb25maWckbl9uZWlnaGJvcnMgPC0gbGVuZ3RoKHNhbXBsZV9uYW1lcyhwc19rcmFrZW5fc3BlY2llcykpLTEKdW1hcC5jb25maWckbWluX2Rpc3QgPC0gLjkKdW1hcC5jb25maWckc3ByZWFkIDwtIDEKdW1hcC5jb25maWckcmFuZG9tX3N0YXRlIDwtIDEyMzQ1NjcKdW1hcC5jb25maWckdHJhbnNmb3JtX3N0YXRlIDwtIDEyMwoKYGBgCgpgYGB7cn0KCmRvX3VtYXBfbWd4MmFtcCA8LSBmdW5jdGlvbihkaXN0Lm1hdHJpeCwgdW1hcF9jb25maWcsam9pbl92YXIpewogICMgUnVuIFVNQVAKICBmdW4udW1hcCA8LSB1bWFwOjp1bWFwKGRpc3QubWF0cml4LCBjb25maWcgPSB1bWFwX2NvbmZpZyxpbnB1dD0iZGlzdCIpCiAgCiAgIyBHZXQgQ29vcmRpbmF0ZXMgZm9yIGdncGxvdDIKICB1bWFwLnB0IDwtIGZ1bi51bWFwJGxheW91dCAlPiUgIAogICAgYXNfdGliYmxlKHJvd25hbWVzID0gTkEpICU+JSAKICAgIHJvd25hbWVzX3RvX2NvbHVtbigpCgogICMgSm9pbiB3aXRoIGV4dHJhIG1ldGFkYXRhLCBjbHVzdGVycywgZXRjLgogIHVtYXAucHQgPC0gdW1hcC5wdCAlPiUgCiAgICBsZWZ0X2pvaW4oc19tZXRhLCBieT1jKCJyb3duYW1lIj1qb2luX3ZhcikpCgogIAogICMgUGxvdCBVTUFQCiAgcC51bWFwIDwtZ2dwbG90KHVtYXAucHQsIGFlcyh4PVYxLCB5PVYyKSkrIAogICAgZ2VvbV9wb2ludChhZXMoY29sb3I9ZmFjdG9yKGNsdXN0ZXJfbnVtKSksc2l6ZT0xLCBhbHBoYT0wKSArIAogICAgdGhlbWVfYncoMTApICsgCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpICsgCiAgICBsYWJzKHg9IlVNQVAxIix5PSJVTUFQMiIpICsKICAgICNzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpKyAgCiAgICBzY2FsZV9jb2xvcl9ucGcoKSArCiAgICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKyAKICAgIGdlb21fcG9pbnQoYWVzKGZpbGw9ZmFjdG9yKGNsdXN0ZXJfbnVtKSksc2l6ZT0yLCBhbHBoYT0xLCBzaGFwZT0yMSkgICsgCiAgICBzY2FsZV9maWxsX25wZygpICsKICAgICNzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICAgIG5hdHVyZV90aGVtZSgiVU1BUDEiLCAiVU1BUDIiKSArIAogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsgdGhlbWUoYXNwZWN0LnJhdGlvPTEpCiAgcC5lbGxpcHNlIDwtIHAudW1hcCArIHN0YXRfZWxsaXBzZShhZXMoY29sb3IgPSBmYWN0b3IoY2x1c3Rlcl9udW0pKSkgIysgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQogICMgT3B0aW9uYWwgUGxvdCB3aXRoIE1hcmdpbmFsIERpc3RyaWJ1dGlvbnMKICBwLm1hcmdpbmFsPC1nZ01hcmdpbmFsKHAudW1hcCwgdHlwZT0iZGVuc2l0eSIsIGdyb3VwRmlsbCA9IFQsIGdyb3VwQ29sb3VyID0gVCkKICByZXR1cm4obGlzdChwLnVtYXAsIHAuZWxsaXBzZSwgcC5tYXJnaW5hbCwgdW1hcC5wdCkpCn0KCnAudW1hcHMuYW1wIDwtIGRvX3VtYXBfbWd4MmFtcChkaXN0LmFtcC5icmF5LCB1bWFwLmNvbmZpZywgInNhbXBsZS5pZCIpCnAudW1hcHMuYW1wW1szXV0KCnAudW1hcHMua3JhayA8LSBkb191bWFwX21neDJhbXAoZGlzdC5rcmFrLmJyYXksIHVtYXAuY29uZmlnLCAic2VxX2lkIikKcC51bWFwcy5rcmFrW1s0XV0gJT4lCiAgbGVmdF9qb2luKG1ldGEpICU+JQogIGdncGxvdCguLCBhZXMoeD1WMSwgeT1WMikpKyAKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yPWZhY3RvcihjbHVzdGVyX251bSkpLHNpemU9MSwgYWxwaGE9MCkgKyAKICAgIGdlb21fcG9pbnQoYWVzKGZpbGw9ZmFjdG9yKGNsdXN0ZXJfbnVtKSksc2l6ZT0yLCBhbHBoYT0xLCBzaGFwZT0yMSkgICsgCiAgICBzdGF0X2VsbGlwc2UoYWVzKGNvbG9yID0gZmFjdG9yKGNsdXN0ZXJfbnVtKSkpICsgCiAgICBzY2FsZV9jb2xvcl9ucGcoKSArCiAgICBzY2FsZV9maWxsX25wZygpICsKICAgIGxhYnMoeD0iVU1BUDEiLHk9IlVNQVAyIikgKwogICAgbmF0dXJlX3RoZW1lKCJVTUFQMSIsICJVTUFQMiIpICsgCiAgICB0aGVtZShhc3BlY3QucmF0aW89MSxsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpCnAudW1hcHMua3Jha1tbM11dCnAudW1hcHMua3Jha1tbNF1dICU+JQogIGxlZnRfam9pbihtZXRhKSAlPiUKICBnZ3Bsb3QoLiwgYWVzKHg9VjEsIHk9VjIpKSsgCiAgICAjZ2VvbV9wb2ludChjb2xvcj0iZ3JleSIsIHNpemU9MSwgYWxwaGE9LjAxKSArIAogICAgZ2VvbV9wb2ludChhZXMoZmlsbD1hbnRpYmlvdGljc180OGgpLHNpemU9MiwgYWxwaGE9MSwgc2hhcGU9MjEpICArIAogICAgc2NhbGVfZmlsbF9ucGcoKSArCiAgICBsYWJzKHg9IlVNQVAxIix5PSJVTUFQMiIpICsKICAgIG5hdHVyZV90aGVtZSgiVU1BUDEiLCAiVU1BUDIiKSArIAogICAgdGhlbWUoYXNwZWN0LnJhdGlvPTEsbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQoKYGBgCgoKCgpgYGB7cn0KbGlicmFyeShhZGU0KQoKdG1wLm1hbnQgPC0gbWFudGVsLnJ0ZXN0KGFzLmRpc3QoZGlzdC5hbXAuYnJheSksIGFzLmRpc3QoZGlzdC5rcmFrLmJyYXkpLCBucmVwZXQgPSA5OTkpCnRtcC5tYW50JF4yCmBgYAoKCgojIFZpc3VhbGl6ZSBTcGVjaWZpYyBGZWF0dXJlcwoKYGBge3J9CgpnZW4ub3R1IDwtIHBzbWVsdChwcy5hc3Qua3JhaykgJT4lIAogIGFycmFuZ2UoU2FtcGxlKSAlPiUKICBtdXRhdGUoT1RVID0gc3RyaW5ncjo6c3RyX3JlcGxhY2Uoc3RyaW5nID0gT1RVLCBwYXR0ZXJuID0gIi0iLCByZXBsYWNlbWVudD0iLiIpKSAlPiUKICAjc2VsZWN0KCFPVFUpICU+JSByZW5hbWUoT1RVPSJHZW5lcmEiKSAlPiUKICBmaWx0ZXIoc3RyaW5ncjo6c3RyX2RldGVjdChPVFUsIHBhc3RlKGRpZmYuZ2VuZXJhLCBjb2xsYXBzZT0ifCIpKSkgI1BsYXNtb2RpdW18SGVycGVzfFRveG9wbGFzbWEKCmdlbi5vdHUkY2x1c3Rlcl9udW0gPC0gYXMuZmFjdG9yKGdlbi5vdHUkY2x1c3Rlcl9udW0pCmFidW5kYW50LmdlbiA8LSBnZW4ub3R1ICU+JSBmaWx0ZXIoQWJ1bmRhbmNlID4gMC4wNSkgJT4lIHNlbGVjdChTcGVjaWVzKSAlPiUgdW5pcXVlKCkgJT4lIHBsdWNrKDEpCmdlbi5vdHUgPC0gZ2VuLm90dSAlPiUgZmlsdGVyKFNwZWNpZXMgJWluJSBhYnVuZGFudC5nZW4pCgpwLmJveC5nZW5lcmEgPC0gZ2VuLm90dSAlPiUKICBmaWx0ZXIoY2x1c3Rlcl9udW0gJWluJSBjKCIxIiwiNSIpKSAlPiUKICBnZ3Bsb3QoLiwgYWVzKHg9Y2x1c3Rlcl9udW0sIHk9QWJ1bmRhbmNlLGZpbGwgPSBjbHVzdGVyX251bSkpICsKICBnZW9tX2JveHBsb3QoYWVzKHk9QWJ1bmRhbmNlKSwgCiAgICAgICAgICAgICAgICAgICAgICBvdXRsaWVyLmFscGhhID0gMC4wLCAKICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IC41LCAKICAgICAgICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX3BvaW50KGFlcyh5PUFidW5kYW5jZSksIAogICAgICAgICAgYWxwaGEgPSAwLjc1ICwKICAgICAgICAgIHNpemUgPSAxLCAKICAgICAgICAgIHNoYXBlID0gMjEsIAogICAgICAgICAgY29sb3IgPSAnYmxhY2snLAogICAgICAgICAgcG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAxKSkgKyAKICBsYWJzKHg9IlBuZXVtb3R5cGUgQ2x1c3RlciIpICsgCiAgc2NhbGVfZmlsbF9ucGcoKSArIAogIG5hdHVyZV90aGVtZSgiUFQiLCAiUmVsYXRpdmUgQWJ1bmRhbmNlIikgKwogIGdndGl0bGUoIlNvbWUgVW51c3VhbCBNaWNyb2JlcyIpICsKICBmYWNldF93cmFwKHZhcnMoU3BlY2llcyksIAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWUiLCAKICAgICAgICAgICAgIHN0cmlwLnBvc2l0aW9uPSJ0b3AiKSArCiAgdGhlbWUoc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgYXNwZWN0LnJhdGlvPTEpICsKICBzdGF0X2NvbXBhcmVfbWVhbnMobGFiZWwueS5ucGMgPSAuOSxzaXplPTIpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpCnAuYm94LmdlbmVyYQpnZ3NhdmUoIi4uLy4uL3Jlc3VsdHMvZmlndXJlcy9Db3J5bmViYWN0ZXJpdW0ucGRmIixwLmJveC5nZW5lcmEsIHdpZHRoPTIwLCBoZWlnaHQ9MjApCiMgZ2VuLm90dSAlPiUKIyAgIGZpbHRlcihTcGVjaWVzPT0iVG94b3BsYXNtYV9nb25kaWkiKSAlPiUKIyAgIGZpbHRlcihBYnVuZGFuY2UgPiAwLjEpCgoKYzI1IDwtIGMoCiAgImRvZGdlcmJsdWUyIiwgIiNFMzFBMUMiLCAjIHJlZAogICJncmVlbjQiLAogICIjNkEzRDlBIiwgIyBwdXJwbGUKICAiI0ZGN0YwMCIsICMgb3JhbmdlCiAgImJsYWNrIiwgImdvbGQxIiwKICAic2t5Ymx1ZTIiLCAiI0ZCOUE5OSIsICMgbHQgcGluawogICJwYWxlZ3JlZW4yIiwKICAiI0NBQjJENiIsICMgbHQgcHVycGxlCiAgIiNGREJGNkYiLCAjIGx0IG9yYW5nZQogICJncmF5NzAiLCAia2hha2kyIiwKICAibWFyb29uIiwgIm9yY2hpZDEiLCAiZGVlcHBpbmsxIiwgImJsdWUxIiwgInN0ZWVsYmx1ZTQiLAogICJkYXJrdHVycXVvaXNlIiwgImdyZWVuMSIsICJ5ZWxsb3c0IiwgInllbGxvdzMiLAogICJkYXJrb3JhbmdlNCIsICJicm93biIKKQpjb2xvdXJDb3VudCA9IGxlbmd0aCh1bmlxdWUoZ2VuLm90dSRTcGVjaWVzKSkKZ2V0UGFsZXR0ZSA9IGNvbG9yUmFtcFBhbGV0dGUoYzI1KQoKcC5zdGFja2VkIDwtIGdlbi5vdHUgJT4lCiAgICBmaWx0ZXIoY2x1c3Rlcl9udW0gJWluJSBjKCIxIiwiNSIpKSAlPiUKICBnZ3Bsb3QoLiwgYWVzKHg9U2FtcGxlLCB5PUFidW5kYW5jZSwgZmlsbD1TcGVjaWVzKSkgKwogIGdlb21fYmFyKGNvbG9yPSJibGFjayIsIHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249ImZpbGwiKSArCiAgeWxhYigiUmVsYXRpdmUgQWJ1bmRhbmNlIikgKwogIGdndGl0bGUoIkFtcGxpY29uIFNlcXVlbmNpbmciKSArIAogIHRoZW1lX3B1YmNsZWFuKCkgKyAKICByb3RhdGVfeF90ZXh0KCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGdldFBhbGV0dGUoY29sb3VyQ291bnQpKSArIAogIHRoZW1lKHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MykpICsgCiAgcm90YXRlX3hfdGV4dChhbmdsZT05MCkgKwogIGZhY2V0X3dyYXAodmFycyhjbHVzdGVyX251bSksIG5jb2w9NSxzY2FsZXMgPSAiZnJlZV94Iiwgc3RyaXAucG9zaXRpb249InRvcCIpCgphX2xlZ2VuZCA8LSBhc19nZ3Bsb3QoY293cGxvdDo6Z2V0X2xlZ2VuZChwLnN0YWNrZWQpKQoKcC5zdGFja2VkICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ2VuLm90dSAlPiUKICBtdXRhdGUoUHJlc2VuY2UgPSBpZl9lbHNlKEFidW5kYW5jZSA+IDAsIDEsIDApLCAuYmVmb3JlPUFidW5kYW5jZSkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4PVNhbXBsZSwgeT1TcGVjaWVzLCBmaWxsPWNsdXN0ZXJfbnVtKSkgKwogIGdlb21fcG9pbnQoYWVzKGFscGhhPVByZXNlbmNlLCBzaXplPUFidW5kYW5jZSksIHNoYXBlPTIxKSArICAKICAjbmF0dXJlX3RoZW1lKCIiLCAiIikgKwogIHRoZW1lKHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MyksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT03LCBmYWNlPSJpdGFsaWMiKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbD1OQSwgbGluZXdpZHRoPTEpKSArIAogIHJvdGF0ZV94X3RleHQoYW5nbGU9OTApICsKICBzY2FsZV9hbHBoYShyYW5nZSA9IGMoMCwgMSkpICsKICBmYWNldF9ncmlkKGNvbHM9dmFycyhjbHVzdGVyX251bSksIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2U9ImZyZWVfeCIpCgpsaWJyYXJ5KGdncmlkZ2VzKQptZWQuc3BwLnZhbHVlcyA8LSBnZW4ub3R1ICU+JSAKICBmaWx0ZXIoY2x1c3Rlcl9udW0gPT0gIjQiKSAlPiUgCiAgZmlsdGVyKEFidW5kYW5jZSA+IDApICU+JSAKICBncm91cF9ieShTcGVjaWVzKSAlPiUgCiAgbXV0YXRlKG1lZCA9IG1lZGlhbihBYnVuZGFuY2UpKSAlPiUgCiAgc2VsZWN0KFNwZWNpZXMsIG1lZCkgJT4lIAogIHVuaXF1ZSgpCgojIGdlbi5vdHUgJT4lCiMgICBtdXRhdGUoUHJlc2VuY2UgPSBpZl9lbHNlKEFidW5kYW5jZSA+IDAsIDEsIDApLCAuYmVmb3JlPUFidW5kYW5jZSkgJT4lCiMgICBsZWZ0X2pvaW4oc2VsZWN0KG1ldGEsIHNhbXBsZS5pZCwgcHRfY2F0ZWdvcnksIHN1Y2Nlc3MpKSAlPiUKIyAgIGxlZnRfam9pbihtZWQuc3BwLnZhbHVlcykgJT4lCiMgICBmaWx0ZXIoUHJlc2VuY2UgPT0gMSkgJT4lCiMgICBncm91cF9ieShTcGVjaWVzKSAlPiUKIyAgIG11dGF0ZV9hdChjKCJBYnVuZGFuY2UiKSwgfihsb2cxMCguL21lZCkpKSAlPiUKIyAgICNtdXRhdGVfYXQoYygiQWJ1bmRhbmNlIiksIH4oc2NhbGUoLiwgc2NhbGU9VFJVRSkgJT4lIGFzLnZlY3RvcikpICU+JQojICAgdW5ncm91cCgpICU+JQojICAgZ2dwbG90KC4sIGFlcyh4PUFidW5kYW5jZSwgeT1jbHVzdGVyX251bSwgZmlsbD1jbHVzdGVyX251bSkpICsKIyAgICAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhzY2FsZT0xMCwgYWxwaGE9LjUpICsKIyAgICAgbmF0dXJlX3RoZW1lKCIiLCAiIikgKwojICAgICBzY2FsZV9maWxsX25wZygpICsKIyAgICAgZmFjZXRfd3JhcCh2YXJzKFNwZWNpZXMpLCBuY29sPTEsc3RyaXAucG9zaXRpb24gPSAicmlnaHQiKSsgCiMgICAgIHRoZW1lKAojICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MSwgYW5nbGU9MCksIAojICAgICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAsICJpbiIpKSArIHhsaW0oLTIuNSwgMi41KSAKbXlwYWwgPC0gcGFsX25wZygibnJjIikoOSkKCnAucmlkZ2UgPC0gZ2VuLm90dSAlPiUKICBtdXRhdGUoUHJlc2VuY2UgPSBpZl9lbHNlKEFidW5kYW5jZSA+IDAsIDEsIDApLCAuYmVmb3JlPUFidW5kYW5jZSkgJT4lCiAgbGVmdF9qb2luKHNlbGVjdChtZXRhLCBzYW1wbGUuaWQsIHB0X2NhdGVnb3J5LCBzdWNjZXNzKSkgJT4lCiAgbGVmdF9qb2luKG1lZC5zcHAudmFsdWVzKSAlPiUKICBmaWx0ZXIoUHJlc2VuY2UgPT0gMSkgJT4lCiAgbXV0YXRlKFNwZWNpZXMgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoU3BlY2llcywgIl8iLCAiICIpKSAlPiUKICBncm91cF9ieShTcGVjaWVzKSAlPiUKICBtdXRhdGVfYXQoYygiQWJ1bmRhbmNlIiksIH4obG9nMTAoLi9tZWQpKSkgJT4lCiAgI211dGF0ZV9hdChjKCJBYnVuZGFuY2UiKSwgfihzY2FsZSguLCBzY2FsZT1UUlVFKSAlPiUgYXMudmVjdG9yKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGdncGxvdCguKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdD1jbHVzdGVyX251bSwgY29sb3I9Y2x1c3Rlcl9udW0pLCBzaXplPS4xKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTAsIGNvbG9yPSJncmV5MzgiKSArCgogICAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhZXMoeD1BYnVuZGFuY2UsIHk9Y2x1c3Rlcl9udW0sIGZpbGw9Y2x1c3Rlcl9udW0sIGNvbG9yPWNsdXN0ZXJfbnVtKSwKICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGU9MTAuMCwgCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsX3NjYWxpbmc9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0PTEsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9LjEsCiAgICAgICAgICAgICAgICAgICAgICAgIGRyYXdfYmFzZWxpbmU9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgcmVsX21pbl9oZWlnaHQgPSAwKSArCiAgICBuYXR1cmVfdGhlbWUoIiIsICIiKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYnJpZ2h0bmVzcyhteXBhbCwgZGVsdGEoLTAuMykpKSArCiAgICBzY2FsZV9maWxsX25wZygpICsKICAgIGZhY2V0X3dyYXAodmFycyhTcGVjaWVzKSwgbmNvbD0xLHN0cmlwLnBvc2l0aW9uID0gInJpZ2h0Iiwgc2NhbGU9ImZyZWVfeSIpKyAKICAgIHRoZW1lKAogICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCNlbGVtZW50X3RleHQoc2l6ZT0xLCBhbmdsZT0wKSwgCiAgICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAsICJpbiIpLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlPSJpdGFsaWMiKSwKICAgICAgc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KHNpemU9OCxhbmdsZSA9IDAsIGhqdXN0ID0gMCwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgICB4bGltKC0yLjUsIDIuNSkgICsKICBsYWJzKHg9ZXhwcmVzc2lvbihsb2dbMTBdKCdhYnVuZGFuY2UgcmVsYXRpdmUgdG8nfn5QWzRdfidtZWRpYW4nKSksCiAgICAgICB5PSJEZW5zaXR5IikgKyBnZ3RpdGxlKCJUYXhvbm9teSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkKICAKcC5yaWRnZSArIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDAuNjE4KQoKZ2dzYXZlKCIuLi8uLi9yZXN1bHRzL0tERVRheG9ub215UGxvdC5wZGYiLCBwbG90PXAucmlkZ2UsIGhlaWdodD0xMCwgd2lkdGg9NSkKYGBgCmBgYHtyfQpwc21lbHQocHNfa3Jha2VuX3NwZWNpZXMpICU+JSAKICBhcnJhbmdlKFNhbXBsZSkgJT4lCiAgbXV0YXRlKE9UVSA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlKHN0cmluZyA9IE9UVSwgcGF0dGVybiA9ICItIiwgcmVwbGFjZW1lbnQ9Ii4iKSkgJT4lIAogICNmaWx0ZXIoU2FtcGxlICVpbiUgYygiRE5BX0IwMl8yNyIpKSAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdChPVFUsICJrX19WaXJ1c2VzIikpICU+JQogIGdyb3VwX2J5KGNsdXN0ZXJfbnVtKSAlPiUKICBzdW1tYXJpemUobWluID0gbWluKEFidW5kYW5jZSksCiAgICAgICAgICAgIHExID0gcXVhbnRpbGUodmFsdWUsIDAuMjUpLAogICAgICAgICAgICBtZWRpYW4gPSBtZWRpYW4odmFsdWUpLAogICAgICAgICAgICBtZWFuID0gbWVhbih2YWx1ZSksCiAgICAgICAgICAgIHEzID0gcXVhbnRpbGUodmFsdWUsIDAuNzUpLAogICAgICAgICAgICBtYXggPSBtYXgodmFsdWUpKQogIGZpbHRlcihzdHJfZGV0ZWN0KE9UVSwgInNfX0NvcnluZWJhY3Rlcml1bV9kaXBodGhlcmlhZSIpKSAlPiUKICBmaWx0ZXIoQWJ1bmRhbmNlPjApICU+JQogIGFycmFuZ2UoZGVzYyhBYnVuZGFuY2UpKQpgYGAKCgojIE1hYXNsaW4gR2VuZXJhCmBgYHtyfQprcmFrZW5fNG1hcyA8LXBzbWVsdChwc19rcmFrZW5fc3BlY2llcykgJT4lIAogIHNlbGVjdChTYW1wbGUsQWJ1bmRhbmNlLCBTcGVjaWVzKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbT1TcGVjaWVzLCB2YWx1ZXNfZnJvbT1BYnVuZGFuY2UpICU+JSAKICBhcnJhbmdlKFNhbXBsZSkgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJTYW1wbGUiKSAlPiUgYXMubWF0cml4KCkKCm1ldGFfNG1hcyA8LSBzYW1wbGVfZGF0YShwc19rcmFrZW5fc3BlY2llcykgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIGFzX3RpYmJsZShyb3duYW1lcyA9IE5BKSAlPiUKICBzZWxlY3Qoc2FtcGxlLmlkLCBzZXFfaWQsIGNsdXN0ZXJfbnVtKSAlPiUgCiAgbGVmdF9qb2luKHNlbGVjdChtZXRhLCBzYW1wbGUuaWQsIHB0X2NhdGVnb3J5LCBzdWNjZXNzLHBhdGllbnQuaWQubnVtKSkgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJzZXFfaWQiKSAlPiUgbXV0YXRlKGNsdXN0ZXJfbnVtID0gaWZfZWxzZShjbHVzdGVyX251bSA9PSAiNCIsICIwIiwgY2x1c3Rlcl9udW0pKQptZXRhXzRtYXMkc3VjY2VzcyA8LSBhcy5mYWN0b3IobWV0YV80bWFzJHN1Y2Nlc3MpCm1ldGFfNG1hcyRwYXRpZW50LmlkLm51bSA8LSBhcy5mYWN0b3IobWV0YV80bWFzJHBhdGllbnQuaWQubnVtKQoKaGVhZChtZXRhXzRtYXMpCmBgYAoKYGBge3J9CmtyYWtlbk1HWCA9IE1hYXNsaW4yKGlucHV0X2RhdGEgICAgID0ga3Jha2VuXzRtYXMsIAogICAgICAgICAgICAgICAgICAgICBpbnB1dF9tZXRhZGF0YSA9IG1ldGFfNG1hcywgCiAgICAgICAgICAgICAgICAgICAgICNtaW5fYWJ1bmRhbmNlICA9IC4wMDEsCiAgICAgICAgICAgICAgICAgICAgIG1pbl9wcmV2YWxlbmNlID0gLjEsCiAgICAgICAgICAgICAgICAgICAgICNub3JtYWxpemF0aW9uICA9ICJUU1MiLAogICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAiQVNUIiwKICAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICAgICAgICAgPSAiLi4vLi4vcmVzdWx0cy9ub3RlYm9va19vdXQvbWFhc2xpbjJfb3V0IiwgCiAgICAgICAgICAgICAgICAgICAgIGZpeGVkX2VmZmVjdHMgID0gYygiY2x1c3Rlcl9udW0iKSwKICAgICAgICAgICAgICAgICAgICAgcmVmZXJlbmNlICAgICAgPSBjKCJjbHVzdGVyX251bSw0IiksCiAgICAgICAgICAgICAgICAgICAgIHJhbmRvbV9lZmZlY3RzID0gYygicGF0aWVudC5pZC5udW0iKSwKICAgICAgICAgICAgICAgICAgICAgY29yZSAgICAgICAgICAgPSA0LHBsb3Rfc2NhdHRlciA9IEZBTFNFCiAgICAgICAgICAgICAgICAgICAgICkgIyBTdWJqZWN0CgptYWFzbGluX25vcm0uZ2VuIDwtIGtyYWtlbk1HWCRyZXN1bHRzICU+JSBhcy5kYXRhLmZyYW1lKCkgCm1hYXNsaW5fbm9ybS5nZW4kT1RVIDwtIHJvd25hbWVzKG1hYXNsaW5fbm9ybS5nZW4pCm1hYXNsaW5fbm9ybS5nZW4gPC0gbWFhc2xpbl9ub3JtLmdlbiAlPiUgCiAgI3NlcGFyYXRlKGZlYXR1cmUsIGludG89YygiQVNWIiwgImZlYXR1cmUiKSwgc2VwID0gIlsuXSIpICU+JSAKICBmaWx0ZXIocXZhbCA8IDAuMDEpICU+JQogIGZpbHRlcihOLm5vdC56ZXJvID4gMjApICU+JQogIGFycmFuZ2UocXZhbCkgJT4lIAogIHNlbGVjdChmZWF0dXJlKSAlPiUgCiAgdW5pcXVlCmRpZmYuZ2VuZXJhIDwtIG1hYXNsaW5fbm9ybS5nZW4kZmVhdHVyZQpzb3J0KGRpZmYuZ2VuZXJhKQpgYGAKYGBge3J9CiMgRm9yIFNwZWNpZXMtTGV2ZWwgQW5hbHlzaXMKc19hYnVuZCA8LSByZWFkX3RzdigiLi4vLi4vcmVzdWx0cy9rcmFrZW4vbWVyZ2VkX2tyYWtlbl9tcGFfcHJvZmlsZS50c3YiKSAlPiUKICByZW5hbWUoY2xhZGVfbmFtZSA9ICIjQ2xhc3NpZmljYXRpb24iKSAlPiUKICBmaWx0ZXIoIWdyZXBsKCJwX18iLCBjbGFkZV9uYW1lKSkgJT4lCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KGNsYWRlX25hbWUsICcuKlxcfCcpKQpyZWFkX3RzdigiLi4vLi4vcmVzdWx0cy9rcmFrZW4vbWVyZ2VkX2tyYWtlbl9tcGFfcHJvZmlsZS50c3YiKSAlPiUKICByZW5hbWUoY2xhZGVfbmFtZSA9ICIjQ2xhc3NpZmljYXRpb24iKSAlPiUKICBmaWx0ZXIoZ3JlcGwoImtfX0V1ayIsIGNsYWRlX25hbWUpKQpzX3RheF90YWIgPC0gc19hYnVuZCAlPiUKICBkcGx5cjo6cmVuYW1lKCJ0YXhvbm9teSIgPSAiY2xhZGVfbmFtZSIpICU+JQogICNmaWx0ZXIoc3RyaW5ncjo6c3RyX2RldGVjdCh0YXhvbm9teSxwYXR0ZXJuID0gImtfX0JhY3RlcmlhIikpICU+JSAjICsvLSBOb24tQmFjcz8KICBkcGx5cjo6c2VsZWN0KHRheG9ub215KSAlPiUKICBkcGx5cjo6bXV0YXRlKFNwZWNpZXMgPSBzdWIoJy4qXFx8JywgJycsIHRheG9ub215KSwKICAgICAgICAgICAgICAgIFNwZWNpZXMgPSBnc3ViKCJzX18iLCAiIiwgU3BlY2llcyksCiAgICAgICAgICAgICAgICBzcGVjX3JvdyA9IHRheG9ub215KSAlPiUjU3BlY2llcykgJT4lCiAgZHBseXI6OnNlbGVjdCgtdGF4b25vbXkpICU+JQogIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJzcGVjX3JvdyIpCgoKc19vdHVfdGFiIDwtIHNfYWJ1bmQgJT4lCiAgZHBseXI6OnJlbmFtZSgidGF4b25vbXkiID0gImNsYWRlX25hbWUiKSAlPiUKICAjZmlsdGVyKHN0cmluZ3I6OnN0cl9kZXRlY3QodGF4b25vbXkscGF0dGVybiA9ICJrX19CYWN0ZXJpYSIpKSAlPiUgIyArLy0gTm9uLUJhY3M/CiAgIyBkcGx5cjo6bXV0YXRlKHRheG9ub215ID0gc3ViKCcuKlxcfCcsICcnLCB0YXhvbm9teSksCiAgIyAgICAgICAgICAgICAgIHRheG9ub215ID0gZ3N1Yigic19fIiwgIiIsIHRheG9ub215KSkgJT4lCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXModmFyID0gInRheG9ub215IikKCm5hbWVzKHNfb3R1X3RhYikgPC0gZ3N1YihuYW1lcyhzX290dV90YWIpLCBwYXR0ZXJuID0gIl9rcmFrZW4ycmVwb3J0LnR4dCIsIHJlcGxhY2VtZW50ID0gIiIpIAoKc19tZXRhIDwtIGRhdGEuZnJhbWUoc2VxX2lkID0gbmFtZXMoc19vdHVfdGFiKSkKCnNfbWV0YSA8LSBzX21ldGEgJT4lCiAgbGVmdF9qb2luKAogICByb3duYW1lc190b19jb2x1bW4obWFwX3RhYmxlKSwgCiAgICBieT1jKCJzZXFfaWQiID0gInJvd25hbWUiKSkgJT4lICAKICBkcGx5cjo6bXV0YXRlKHNhbXBsZU5hbWVzX3JvdyA9IHNlcV9pZCkgJT4lCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXModmFyID0gInNhbXBsZU5hbWVzX3JvdyIpICU+JQogIGRyb3BfbmEodHViZSkgJT4lCiAgbXV0YXRlKHNhbXBsZS5pZCA9IHBhc3RlMCgiUFQiLCBTYW1wbGUsICItVFVCRSIsIHR1YmUpKQoKcHNfa3Jha2VuX3BoeWxhIDwtIHBoeWxvc2VxKHNhbXBsZV9kYXRhKHNfbWV0YSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3R1X3RhYmxlKHNfb3R1X3RhYiwgdGF4YV9hcmVfcm93cyA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheF90YWJsZShhcy5tYXRyaXgoc190YXhfdGFiKSkpCgojIEluaXRpYWwgZmlsdGVyaW5nCnBzX2tyYWtlbl9waHlsYSA8LSBmaWx0ZXJfdGF4YShwc19rcmFrZW5fcGh5bGEsIGZ1bmN0aW9uKHgpe3N1bSh4ID4gMykgPiAwfSwgcHJ1bmUgPSBUUlVFKQpwc19rcmFrZW5fcGh5bGEgPC0gcHJ1bmVfc2FtcGxlcyhzYW1wbGVfc3Vtcyhwc19rcmFrZW5fcGh5bGEpID4gNTAwMCwgcHNfa3Jha2VuX3BoeWxhKQoKcHNfa3Jha2VuX3BoeWxhLmNzcyA8LSBwc19rcmFrZW5fcGh5bGEKb3R1X3RhYmxlKHBzX2tyYWtlbl9waHlsYS5jc3MpIDwtIG90dV90YWJsZShNUmNvdW50cyhwc19rcmFrZW5fcGh5bGEgJT4lIHBoeWxvc2VxX3RvX21ldGFnZW5vbWVTZXEoKSwgbm9ybSA9IFRSVUUsIGxvZyA9IEZBTFNFKSx0YXhhX2FyZV9yb3dzPVRSVUUpCgoKIyBSZWxhdGl2ZSBBYnVuZGFuY2UgVHJhbnNmb3JtCnBzX2tyYWtlbl9waHlsYSA8LSBtaWNyb2Jpb21lOjp0cmFuc2Zvcm0ocHNfa3Jha2VuX3BoeWxhLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJjb21wb3NpdGlvbmFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PSJTcGVjaWVzIikgIyAiU3BlY2llcyIgT1IgIkdlbnVzIgoKcHNfa3Jha2VuX3BoeWxhCgpwcy5hc3Qua3Jhay5waHkgPC0gcHNfa3Jha2VuX3BoeWxhCm90dS5hc3Qua3Jhay5waHkgPC0gcHNtZWx0KHBzLmFzdC5rcmFrLnBoeSkgJT4lIAogIG11dGF0ZShBYnVuZGFuY2UgPSBzaWduKEFidW5kYW5jZSkqYXNpbihzcXJ0KGFicyhBYnVuZGFuY2UpKSkpICU+JSAjIGlmIHdhbnQgQVNUIHRyYW5zZm9ybQogIGFycmFuZ2UoU2FtcGxlKSAlPiUKICBzZWxlY3QoU2FtcGxlLCBPVFUsIEFidW5kYW5jZSkgJT4lCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IE9UVSwgbmFtZXNfZnJvbSA9IFNhbXBsZSwgdmFsdWVzX2Zyb20gPSBBYnVuZGFuY2UpICU+JQogIGNvbHVtbl90b19yb3duYW1lcyh2YXI9Ik9UVSIpICU+JSAKICBhcy5tYXRyaXgoKSAKb3R1X3RhYmxlKHBzLmFzdC5rcmFrLnBoeSkgPC0gb3R1X3RhYmxlKG90dS5hc3Qua3Jhay5waHksIHRheGFfYXJlX3Jvd3MgPSBUUlVFKQoKYGBgCgoKYGBge3J9CnBoeS5hYnVuZCA8LXBzbWVsdChwcy5hc3Qua3Jhay5waHkpICU+JSAKICBzZWxlY3QoU2FtcGxlLEFidW5kYW5jZSwgU3BlY2llcyxjbHVzdGVyX251bSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb209U3BlY2llcywgdmFsdWVzX2Zyb209QWJ1bmRhbmNlKSAlPiUgCiAgYXJyYW5nZShTYW1wbGUpICU+JQogIGNvbHVtbl90b19yb3duYW1lcygiU2FtcGxlIikKCnBoeS5hYnVuZCAlPiUKICAjIG11dGF0ZShrX19WaXJ1c2VzID0gbG9nMTAoa19fVmlydXNlcyksCiAgIyAgICAgICAga19fQmFjdGVyaWEgPSBsb2cxMChrX19CYWN0ZXJpYSksCiAgIyAgICAgICAga19fRXVrYXJ5b3RhID0gbG9nMTAoa19fRXVrYXJ5b3RhKSkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4PWtfX0JhY3RlcmlhLCB5PWtfX0V1a2FyeW90YSkpICsKICBnZW9tX3BvaW50KCkrI2FlcyhzaXplPWtfX1ZpcnVzZXMsIGZpbGw9Y2x1c3Rlcl9udW0pLCBzaGFwZT0yMSwgYWxwaGE9LjYpICsKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIikgKwogIG5hdHVyZV90aGVtZSgiIiwiIikgKwogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpICsKICBzY2FsZV9maWxsX25wZygpIAoKcHNtZWx0KHBzX2tyYWtlbl9waHlsYSkgJT4lIAogIHNlbGVjdChTYW1wbGUsQWJ1bmRhbmNlLCBTcGVjaWVzLGNsdXN0ZXJfbnVtKSAlPiUKIyBtdXRhdGUoa19fVmlydXNlcyA9IGxvZzEwKGtfX1ZpcnVzZXMpLAogICMgICAgICAgIGtfX0JhY3RlcmlhID0gbG9nMTAoa19fQmFjdGVyaWEpLAogICMgICAgICAgIGtfX0V1a2FyeW90YSA9IGxvZzEwKGtfX0V1a2FyeW90YSkpICU+JQogIGdncGxvdCguLCBhZXMoeD1jbHVzdGVyX251bSwgeT1BYnVuZGFuY2UsIGZpbGw9U3BlY2llcywgZ3JvdXA9Y2x1c3Rlcl9udW0pKSArCiAgZ2VvbV9ib3hwbG90KGFlcyhmaWxsPVNwZWNpZXMpLCBvdXRsaWVyLmFscGhhID0gMCkgKwogIGdlb21fcG9pbnQoYWVzKGZpbGw9U3BlY2llcyksIAogICAgICAgICAgICAgYWxwaGEgPSAwLjc1LAogICAgICAgICAgICAgc2l6ZSA9IDEsIAogICAgICAgICAgICAgc2hhcGUgPSAyMSwgCiAgICAgICAgICAgICBjb2xvciA9ICdibGFjaycsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IC41KSkgKwogIHNjYWxlX2ZpbGxfc2ltcHNvbnMoKSArCiAgbmF0dXJlX3RoZW1lKCJSZWFkIiwgIkZvbCIpICsKICBsYWJzKHg9IlBuZXVtb3R5cGUgQ2x1c3RlciIgLCAKICAgICAgIHk9IkRvbWFpbiBBYnVuZGFuY2UiLCAKICAgICAgIHRpdGxlPSJEb21haW4gTGV2ZWwgU2hpZnRzIGluIE1ldGFnZW5vbWljIERhdGEgIChBU1QgTm9ybWFsaXplZCkiKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMSkgKyBmYWNldF9ncmlkKH5TcGVjaWVzKSArIAogIHN0YXRfY29tcGFyZV9tZWFucyhsYWJlbC55Lm5wYyA9IC45NSxzaXplPTIsbGFiZWwueC5ucGMgPSAiY2VudGVyIikKCgpwc21lbHQocHNfa3Jha2VuX3BoeWxhKSAlPiUgCiAgc2VsZWN0KFNhbXBsZSxBYnVuZGFuY2UsIFNwZWNpZXMsY2x1c3Rlcl9udW0pICU+JQojIG11dGF0ZShrX19WaXJ1c2VzID0gbG9nMTAoa19fVmlydXNlcyksCiAgIyAgICAgICAga19fQmFjdGVyaWEgPSBsb2cxMChrX19CYWN0ZXJpYSksCiAgIyAgICAgICAga19fRXVrYXJ5b3RhID0gbG9nMTAoa19fRXVrYXJ5b3RhKSkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4PWNsdXN0ZXJfbnVtLCB5PUFidW5kYW5jZSwgZmlsbD1TcGVjaWVzLCBncm91cD1jbHVzdGVyX251bSkpICsKICBnZW9tX2JveHBsb3QoYWVzKGZpbGw9U3BlY2llcyksIG91dGxpZXIuYWxwaGEgPSAwKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbD1TcGVjaWVzKSwgCiAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsCiAgICAgICAgICAgICBzaXplID0gMSwgCiAgICAgICAgICAgICBzaGFwZSA9IDIxLCAKICAgICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gLjUpKSArCiAgc2NhbGVfZmlsbF9zaW1wc29ucygpICsKICBuYXR1cmVfdGhlbWUoIlJlYWQiLCAiRm9sIikgKwogIGxhYnMoeD0iUG5ldW1vdHlwZSBDbHVzdGVyIiAsIAogICAgICAgeT0iRG9tYWluIEFidW5kYW5jZSIsIAogICAgICAgdGl0bGU9IkRvbWFpbiBMZXZlbCBTaGlmdHMgaW4gTWV0YWdlbm9taWMgRGF0YSAgKEFTVCBOb3JtYWxpemVkKSIpICsKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKSArIGZhY2V0X2dyaWQoflNwZWNpZXMpICsgCiAgc3RhdF9jb21wYXJlX21lYW5zKGxhYmVsLnkubnBjID0gLjk1LHNpemU9MixsYWJlbC54Lm5wYyA9ICJjZW50ZXIiKQoKcHNtZWx0KHBzX2tyYWtlbl9waHlsYSkgJT4lIAogIHNlbGVjdChTYW1wbGUsQWJ1bmRhbmNlLCBTcGVjaWVzLGNsdXN0ZXJfbnVtKSAlPiUKbXV0YXRlKGtfX1ZpcnVzZXMgPSBsb2cxMChrX19WaXJ1c2VzKSwKICAgICAgIGtfX0JhY3RlcmlhID0gbG9nMTAoa19fQmFjdGVyaWEpLAogICAgICAga19fRXVrYXJ5b3RhID0gbG9nMTAoa19fRXVrYXJ5b3RhKSkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4PWNsdXN0ZXJfbnVtLCB5PUFidW5kYW5jZSwgZmlsbD1TcGVjaWVzLCBncm91cD1jbHVzdGVyX251bSkpICsKICBnZW9tX2JveHBsb3QoYWVzKGZpbGw9U3BlY2llcyksIG91dGxpZXIuYWxwaGEgPSAwKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbD1TcGVjaWVzKSwgCiAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsCiAgICAgICAgICAgICBzaXplID0gMSwgCiAgICAgICAgICAgICBzaGFwZSA9IDIxLCAKICAgICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gLjUpKSArCiAgc2NhbGVfZmlsbF9zaW1wc29ucygpICsKICBuYXR1cmVfdGhlbWUoIlJlYWQiLCAiRm9sIikgKwogIGxhYnMoeD0iUG5ldW1vdHlwZSBDbHVzdGVyIiAsIAogICAgICAgeT0iRG9tYWluIEFidW5kYW5jZSIsIAogICAgICAgdGl0bGU9IkRvbWFpbiBMZXZlbCBTaGlmdHMgaW4gTWV0YWdlbm9taWMgRGF0YSAgKEFTVCBOb3JtYWxpemVkKSIpICsKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKSArIGZhY2V0X2dyaWQoflNwZWNpZXMpICsgCiAgc3RhdF9jb21wYXJlX21lYW5zKGxhYmVsLnkubnBjID0gLjk1LHNpemU9MixsYWJlbC54Lm5wYyA9ICJjZW50ZXIiKQoKbGlicmFyeShnZ3Rlcm4pCnBoeS5hYnVuZCAlPiUKICBnZ3Rlcm4oLiwgYWVzKHg9a19fQmFjdGVyaWEsIHk9a19fVmlydXNlcywgej1rX19FdWthcnlvdGEpKSArCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZV9yZ2J3KCkgKwogIGxhYnModGl0bGUgPSAiRXhhbXBsZSBEZW5zaXR5L0NvbnRvdXIgUGxvdCIpICAgICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibHVlIixoaWdoID0gInJlZCIpICArCiAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiLCBmaWxsID0gIm5vbmUiLCBhbHBoYSA9ICJub25lIikKICAKYGBgCgoKCgo=